package sdk

import (
	"context"
	"encoding/json"
	"fmt"
	"net/url"
)

// ConsoleClient 提供控制台相关的 API 操作
type ConsoleClient struct {
	client *APIClient
}

// NewConsoleClient 创建新的控制台客户端
func NewConsoleClient(client *APIClient) *ConsoleClient {
	return &ConsoleClient{
		client: client,
	}
}

// GetSerialConsoleInfo 获取串行控制台信息
func (c *ConsoleClient) GetSerialConsoleInfo(ctx context.Context, connectionID, domainName string) (map[string]interface{}, error) {
	// 构建带查询参数的URL
	u := fmt.Sprintf("/api/v1/console/serial/info?connection=%s&name=%s", url.QueryEscape(connectionID), url.QueryEscape(domainName))

	data, err := c.client.Get(ctx, u)
	if err != nil {
		return nil, fmt.Errorf("failed to get serial console info: %w", err)
	}

	var result map[string]interface{}
	if err := json.Unmarshal(data, &result); err != nil {
		return nil, fmt.Errorf("failed to unmarshal serial console info: %w", err)
	}

	return result, nil
}

// GetVNCInfo 获取VNC控制台信息
func (c *ConsoleClient) GetVNCInfo(ctx context.Context, connectionID, domainName string) (map[string]interface{}, error) {
	// 构建带查询参数的URL
	u := fmt.Sprintf("/api/v1/console/vnc/info?connection=%s&name=%s", url.QueryEscape(connectionID), url.QueryEscape(domainName))

	data, err := c.client.Get(ctx, u)
	if err != nil {
		return nil, fmt.Errorf("failed to get VNC console info: %w", err)
	}

	var result map[string]interface{}
	if err := json.Unmarshal(data, &result); err != nil {
		return nil, fmt.Errorf("failed to unmarshal VNC console info: %w", err)
	}

	return result, nil
}

// GetSPICEInfo 获取SPICE控制台信息
func (c *ConsoleClient) GetSPICEInfo(ctx context.Context, connectionID, domainName string) (map[string]interface{}, error) {
	// 构建带查询参数的URL
	u := fmt.Sprintf("/api/v1/console/spice/info?connection=%s&name=%s", url.QueryEscape(connectionID), url.QueryEscape(domainName))

	data, err := c.client.Get(ctx, u)
	if err != nil {
		return nil, fmt.Errorf("failed to get SPICE console info: %w", err)
	}

	var result map[string]interface{}
	if err := json.Unmarshal(data, &result); err != nil {
		return nil, fmt.Errorf("failed to unmarshal SPICE console info: %w", err)
	}

	return result, nil
}

// GetConsoleInfos 获取虚拟机所有可用控制台信息
func (c *ConsoleClient) GetConsoleInfos(ctx context.Context, connectionID, domainName string) (map[string]interface{}, error) {
	// 构建带查询参数的URL
	u := fmt.Sprintf("/api/v1/console/info?connection=%s&name=%s", url.QueryEscape(connectionID), url.QueryEscape(domainName))

	data, err := c.client.Get(ctx, u)
	if err != nil {
		return nil, fmt.Errorf("failed to get console info: %w", err)
	}

	var result map[string]interface{}
	if err := json.Unmarshal(data, &result); err != nil {
		return nil, fmt.Errorf("failed to unmarshal console info: %w", err)
	}

	return result, nil
}

// CloseVMSerialSessions 关闭虚拟机串行会话
func (c *ConsoleClient) CloseVMSerialSessions(ctx context.Context, connectionID, domainName string) error {
	// 构建带查询参数的URL
	u := fmt.Sprintf("/api/v1/console/serial/sessions?connection=%s&name=%s", url.QueryEscape(connectionID), url.QueryEscape(domainName))

	_, err := c.client.Delete(ctx, u)
	if err != nil {
		return fmt.Errorf("failed to close VM serial sessions: %w", err)
	}
	return nil
}

// GenerateConsoleURL 生成控制台访问URL（用于WebSocket连接）
func (c *ConsoleClient) GenerateConsoleURL(ctx context.Context, consoleType, connectionID, domainName string) (string, string, error) {
	// 首先获取所有控制台信息
	result, err := c.GetConsoleInfos(ctx, connectionID, domainName)
	if err != nil {
		return "", "", fmt.Errorf("failed to get console info: %w", err)
	}

	// 检查请求的控制台类型是否可用
	consolesVal, ok := result["consoles"]
	if !ok {
		return "", "", fmt.Errorf("invalid console info format: consoles field not found")
	}

	consoles, ok := consolesVal.(map[string]interface{})
	if !ok {
		return "", "", fmt.Errorf("invalid console info format: consoles field is not a map")
	}

	consoleInfoVal, exists := consoles[consoleType]
	if !exists {
		return "", "", fmt.Errorf("console type '%s' is not available for domain '%s'", consoleType, domainName)
	}

	consoleInfo, ok := consoleInfoVal.(map[string]interface{})
	if !ok {
		return "", "", fmt.Errorf("invalid console info format: console info for '%s' is not a map", consoleType)
	}

	proxyURLVal, ok := consoleInfo["proxy_url"]
	if !ok {
		return "", "", fmt.Errorf("invalid console info format: proxy_url not found for console type '%s'", consoleType)
	}

	wsPathVal, ok := consoleInfo["ws_path"]
	if !ok {
		return "", "", fmt.Errorf("invalid console info format: ws_path not found for console type '%s'", consoleType)
	}

	proxyPath, ok := proxyURLVal.(string)
	if !ok {
		return "", "", fmt.Errorf("invalid console info format: proxy_url for console type '%s' is not a string", consoleType)
	}

	wsPath, ok := wsPathVal.(string)
	if !ok {
		return "", "", fmt.Errorf("invalid console info format: ws_path for console type '%s' is not a string", consoleType)
	}

	return proxyPath, wsPath, nil
}
